package com.ibeeking.found.upms.g.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.config.feign.GlobalClient;
import com.ibeeking.found.common.config.feign.TenantDataPushClient;
import com.ibeeking.found.common.constants.GlobalConstant;
import com.ibeeking.found.common.entity.*;
import com.ibeeking.found.common.enums.ApplicationEnum;
import com.ibeeking.found.common.enums.FrontendTypeEnum;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.DataPushUtils;
import com.ibeeking.found.upms.api.common.dto.PermissionDTO;
import com.ibeeking.found.upms.g.rest.service.IGmcPermissionService;
import com.ibeeking.found.upms.g.rest.service.IGmcRolePermissionService;
import com.ibeeking.found.upms.g.rest.service.IGmcRoleService;
import com.ibeeking.found.upms.service.common.bo.PermissionBO;
import com.ibeeking.found.upms.service.common.bo.PermissionTreeBO;
import com.ibeeking.found.upms.service.common.bo.RolePermissionBO;
import com.ibeeking.found.upms.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.upms.service.common.dos.*;
import com.ibeeking.found.upms.service.common.param.PermissionCopyParam;
import com.ibeeking.found.upms.service.common.param.PermissionParam;
import com.ibeeking.found.upms.service.common.query.PermissionQuery;
import com.ibeeking.found.upms.service.common.vo.CurrentPermissionVO;
import com.ibeeking.found.upms.service.common.vo.FrontEndTypeVO;
import com.ibeeking.found.upms.service.common.vo.PermissionTreeVO;
import com.ibeeking.found.upms.service.common.vo.PermissionVO;
import com.ibeeking.found.upms.service.mapper.CsPermissionMapper;
import com.ibeeking.found.upms.service.mapper.PermissionMapper;
import com.ibeeking.found.upms.service.mapper.ShopPermissionMapper;
import com.ibeeking.found.upms.service.mapper.TenantPermissionMapper;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.annotation.CacheEvict;
import com.ibeeking.nematos.redis.annotation.CacheQuery;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.base.LongBaseTree;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.SqlUtils;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.data.TreeFastUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName GmcPermissionServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2020-12-01 18:15
 **/
@Service
public class GmcPermissionServiceImpl extends ServiceImpl<PermissionMapper, PermissionDO> implements IGmcPermissionService {

    private static final Integer MENU_TYPE = 3;

    @Resource
    private PermissionMapper permissionMapper;
    @Resource
    private RedisUtils redisUtils;
    @Resource
    private IGmcRoleService roleServiceImpl;
    @Resource
    private IGmcRolePermissionService rolePermissionServiceImpl;
    @Resource
    private TenantPermissionMapper tenantPermissionMapper;
    @Resource
    private ShopPermissionMapper shopPermissionMapper;
    @Resource
    private CsPermissionMapper csPermissionMapper;
    @Resource
    private GlobalClient globalClient;
    @Resource
    private TenantDataPushClient tenantDataPushClient;

    @Override
    public List<PermissionTreeVO> queryList(PermissionQuery permissionQuery) {
        LambdaQueryWrapper<PermissionDO> queryWrapper = new LambdaQueryWrapper<>(PermissionDO.class);

        queryWrapper.eq(null != permissionQuery.getPublishStatus(), PermissionDO::getPublishStatus, permissionQuery.getPublishStatus());
        queryWrapper.eq(PermissionDO::getIndustry, permissionQuery.getIndustry());
        queryWrapper.eq(PermissionDO::getModule, permissionQuery.getModule());
        queryWrapper.eq(PermissionDO::getParentId, permissionQuery.getParentId());
        queryWrapper.eq(null != permissionQuery.getType(), PermissionDO::getType, permissionQuery.getType());
        queryWrapper.like(StringUtils.isNotBlank(permissionQuery.getName()), PermissionDO::getName, permissionQuery.getName());

        List<PermissionDO> permissionDOS = permissionMapper.selectList(queryWrapper);
        if (Collections3.isEmpty(permissionDOS)) {
            return Collections3.emptyList();
        }
        List<Long> ids = permissionDOS.stream().map(BaseDO::getId).collect(Collectors.toList());
        ids.add(permissionQuery.getParentId());
        //查询所有菜单
        List<PermissionDO> all = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, permissionQuery.getIndustry())
                .eq(PermissionDO::getModule, permissionQuery.getModule())
                .orderByAsc(PermissionDO::getSort));
        List<PermissionTreeVO> allTrees = JsonUtils.jsonToList(all, PermissionTreeVO.class);

        List<Long> result = new ArrayList<>();
        TreeFastUtils.selectLongCidByPid(result, allTrees, ids);
        result.addAll(ids);
        allTrees = allTrees.stream().filter(g -> result.contains(g.getId())).collect(Collectors.toList());
        Map<Long, String> names = allTrees.parallelStream().collect(Collectors.toMap(LongBaseTree::getId, PermissionTreeVO::getName));
        allTrees.parallelStream().filter(permissionTreeVO -> names.containsKey(permissionTreeVO.getParentId())).forEach(permissionTreeVO -> permissionTreeVO.setParentName(names.get(permissionTreeVO.getParentId())));
        return TreeFastUtils.listToTree(allTrees, permissionQuery.getParentId());
    }

    @CacheQuery(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.PERMISSION_TREE, key = "#permissionQuery.industry + '-' + #permissionQuery.module", expires = RedisKeyConstant.MONTH)
    @Override
    public List<PermissionTreeVO> queryListCache(PermissionQuery permissionQuery) {
        return getBean().queryList(permissionQuery);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(PermissionParam permissionParam) {
        if (null == permissionParam.getParentId()) {
            permissionParam.setParentId(GlobalConstant.PARENT_ID);
        }
        IGmcPermissionService bean = getBean();
        Long id1 = bean.checkName(permissionParam.getName(), permissionParam.getParentId(), permissionParam.getIndustry(), permissionParam.getModule());
        if (null != id1) {
            throw new BusinessException("存在同名权限菜单");
        }

        if (MENU_TYPE.equals(permissionParam.getType())) {
            Long id2 = bean.checkPermission(permissionParam.getPermission(), permissionParam.getModule(), permissionParam.getIndustry());
            if (null != id2) {
                throw new BusinessException("菜单按钮权限值禁止相同");
            }
        }
        PermissionDO permissionDO = BeanUtil.convertBean(permissionParam, PermissionDO.class);
        permissionDO.setCreateTime(LocalDateTime.now());
        permissionDO.setModifyTime(LocalDateTime.now());
        if (GlobalConstant.PARENT_ID.equals(permissionDO.getParentId())) {
            permissionDO.setLevel(1);
        } else {
            //查询父级目录级别
            PermissionBO permissionBO = bean.queryById(permissionDO.getParentId());
            permissionDO.setLevel(permissionBO.getLevel() + 1);
        }
        permissionMapper.insert(permissionDO);
        getBean().syncAdd(permissionDO);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.PERMISSION, key = "#permissionParam.id")
    @Override
    public Boolean modify(PermissionParam permissionParam) {
        IGmcPermissionService bean = getBean();
        PermissionBO permissionBO = bean.queryById(permissionParam.getId());
        Long id1 = bean.checkName(permissionParam.getName(), permissionBO.getParentId(), permissionParam.getIndustry(), permissionBO.getModule());

        if (null != id1 && !id1.equals(permissionParam.getId())) {
            throw new BusinessException("存在同名权限菜单");
        }

        if (MENU_TYPE.equals(permissionBO.getType())) {
            Long id2 = bean.checkPermission(permissionParam.getPermission(), permissionBO.getModule(), permissionBO.getIndustry());
            if (null != id2 && !id2.equals(permissionParam.getId())) {
                throw new BusinessException("菜单按钮权限值禁止相同");
            }
        }

        PermissionDO permissionDO = BeanUtil.convertBean(permissionParam, PermissionDO.class);
        permissionDO.setParentId(null);
        permissionDO.setIndustry(permissionBO.getIndustry());
        permissionDO.setModule(permissionBO.getModule());
        permissionDO.setType(permissionParam.getType());
        permissionDO.setModifyTime(LocalDateTime.now());
        permissionMapper.updateById(permissionDO);

        getBean().syncModify(permissionDO);
        return true;
    }

    @Override
    public Boolean copyFromIndustry(PermissionCopyParam param){
        if(StringUtils.isEmpty(param.getModule()) || StringUtils.isEmpty(param.getFrom()) || StringUtils.isEmpty(param.getTo())){
            throw new BusinessException("业务端或行业选择不能为空！");
        }
        ResponseResult<List<DatabaseTemplateDTO>> responseResult = globalClient.listTemplateByIndustry(param.getTo());
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            throw new BusinessException("请先配置行业模板库！");
        }
        List<PermissionDO> copyPermissionDOS = new ArrayList<>();
        List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, param.getFrom())
                .eq(PermissionDO::getModule, param.getModule()));
        if (Collections3.isNotEmpty(permissionDOS)) {
            Long curentDateLng = LocalDateTime.now().getLong(ChronoField.MILLI_OF_DAY);
            copyPermissionDOS = permissionDOS.stream().map(s->{
                PermissionDO entityDO = BeanUtil.convertBean(s, PermissionDO.class);
                Long id = entityDO.getId();
                Long parentId = entityDO.getParentId();
                entityDO.setId(id + curentDateLng);
                if(parentId != GlobalConstant.PARENT_ID){
                    entityDO.setParentId(parentId + curentDateLng);
                }
                entityDO.setIndustry(param.getTo());
                entityDO.setCreateTime(LocalDateTime.now());
                entityDO.setModifyTime(LocalDateTime.now());
                return entityDO;
            }).collect(Collectors.toList());
            permissionMapper.insertBatchSomeColumn(copyPermissionDOS);

            getBean().syncCopy(param.getTo(), param.getModule(), copyPermissionDOS);
        }
        return true;
    }

    @Override
    public PermissionVO view(Long id) {
        IGmcPermissionService bean = getBean();
        PermissionBO permissionBO = bean.queryById(id);
        if (null == permissionBO) {
            return null;
        }
        PermissionVO permissionVO = BeanUtil.convertBean(permissionBO, PermissionVO.class);
        if (GlobalConstant.PARENT_ID.equals(permissionBO.getParentId())) {
            permissionVO.setParentName(GlobalConstant.PARENT_NAME);
        } else {
            PermissionBO permissionBO1 = bean.queryById(permissionBO.getParentId());
            permissionVO.setParentName(null != permissionBO1 ? permissionBO1.getName() : "");
        }
        return permissionVO;
    }

    @CacheQuery(cacheName = RedisKeyConstant.MODULE_G + RedisKeyConstant.PERMISSION, key = "#id", expires = RedisKeyConstant.MONTH)
    @Override
    public PermissionBO queryById(Long id) {
        PermissionDO permissionDO = permissionMapper.selectById(id);
        return BeanUtil.convertBean(permissionDO, PermissionBO.class);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer status, Long modifyBy) {
        PermissionBO permissionBO = getBean().queryById(id);
        if (null == permissionBO) {
            return true;
        }

        List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, permissionBO.getIndustry())
                .eq(PermissionDO::getModule, permissionBO.getModule()));
        if (Collections3.isEmpty(permissionDOS)) {
            return true;
        }
        List<Long> ids = new ArrayList<>();
        if (PublishStatusEnum.ENABLE.getValue().equals(status)) {
            //将所有父项都启用
            TreeFastUtils.selectLongPidByCid(ids, JsonUtils.jsonToList(permissionDOS, PermissionTreeBO.class), Collections.singletonList(id));
        } else {
            //将所有子项都禁用
            TreeFastUtils.selectLongCidByPid(ids, JsonUtils.jsonToList(permissionDOS, PermissionTreeBO.class), Collections.singletonList(id));
        }
        ids.add(id);
        List<PermissionDO> update = new ArrayList<>();
        List<String> cache = new ArrayList<>();
        ids.forEach(key -> {
            PermissionDO permissionDO = new PermissionDO();
            permissionDO.setId(key);
            permissionDO.setPublishStatus(status);
            permissionDO.setModifyBy(modifyBy);
            permissionDO.setModifyTime(LocalDateTime.now());
            update.add(permissionDO);
            cache.add(RedisKeyConstant.MODULE_G + RedisKeyConstant.PERMISSION + id);
        });
        this.updateBatchById(update);
        //清除缓存
        redisUtils.del(cache);

        //同步修改状态
        getBean().syncChangeStatus(permissionBO.getIndustry(), permissionBO.getModule(), ids, status);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        PermissionBO permissionBO = getBean().queryById(id);
        if (null == permissionBO) {
            return true;
        }
        if (PublishStatusEnum.ENABLE.getValue().equals(permissionBO.getPublishStatus())) {
            throw new BusinessException("请先禁用后再删除");
        }

        //删除所有子项
        List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, permissionBO.getIndustry())
                .eq(PermissionDO::getModule, permissionBO.getModule()));
        if (Collections3.isEmpty(permissionDOS)) {
            return true;
        }

        //查询所有子项id
        List<Long> ids = new ArrayList<>();
        TreeFastUtils.selectLongCidByPid(ids, JsonUtils.jsonToList(permissionDOS, PermissionTreeBO.class), Collections.singletonList(id));
        ids.add(id);
        permissionMapper.deleteBatchIds(ids);
        List<String> cache = new ArrayList<>();
        ids.forEach(key -> {
            cache.add(RedisKeyConstant.MODULE_G + RedisKeyConstant.PERMISSION + id);
        });
        redisUtils.del(cache);

        //同步删除
        getBean().syncDel(permissionBO.getIndustry(), permissionBO.getModule(), ids);
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean clearMenuByIndustry(String industry, String frontend){
        if(StringUtils.isEmpty(industry) || StringUtils.isEmpty(frontend)){
            throw new BusinessException("业务端或行业选择不能为空！");
        }
        ResponseResult<List<DatabaseTemplateDTO>> responseResult = globalClient.listTemplateByIndustry(industry);
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            throw new BusinessException("不存在行业模板库！");
        }
        List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, industry)
                .eq(PermissionDO::getModule, frontend));
        if (Collections3.isEmpty(permissionDOS)) {
            return true;
        }
        List<Long> ids = permissionDOS.parallelStream().map(PermissionDO::getId).collect(Collectors.toList());
        permissionMapper.delete(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getIndustry, industry)
                .eq(PermissionDO::getModule, frontend));
        //同步删除
        getBean().syncDel(industry, frontend, ids);
        return true;
    }

    @Override
    public Long checkName(String name, Long parentId, String industry, String module) {
        PermissionDO permissionDO = permissionMapper.selectOne(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getName, name)
                .eq(PermissionDO::getParentId, parentId)
                .eq(PermissionDO::getIndustry, industry)
                .eq(PermissionDO::getModule, module)
        );
        return null != permissionDO ? permissionDO.getId() : null;
    }

    @Override
    public Long checkPermission(String permission, String module, String industry) {
        PermissionDO permissionDO = permissionMapper.selectOne(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(PermissionDO::getPermission, permission)
                .eq(PermissionDO::getModule, module)
                .eq(PermissionDO::getIndustry, industry)
        );
        return null != permissionDO ? permissionDO.getId() : null;
    }

    @Override
    public List<PermissionBO> queryAllList(String module, Integer publishStatus, List<Long> ids) {
        List<PermissionDO> permissionDOS = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .eq(null != publishStatus, PermissionDO::getPublishStatus, publishStatus)
                .eq(PermissionDO::getModule, module)
                .eq(PermissionDO::getModule, module)
                .in(!Collections3.isEmpty(ids), BaseDO::getId, ids)
                .orderByAsc(PermissionDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
        );
        if (Collections3.isEmpty(permissionDOS)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(permissionDOS, PermissionBO.class);
    }

    @Override
    public List<CurrentPermissionVO> queryEffectiveList(CurrentUser currentUser, String jti) {
        List<CurrentPermissionVO> result;
        //1 从缓存中查询
        //从缓存中查询用户权限
        Object o = redisUtils.hGet(RedisKeyConstant.MODULE_G + RedisKeyConstant.USER_PERMISSION + currentUser.getId(), jti);
        if (null != o) {
            result = JsonUtils.jsonToList(o, CurrentPermissionVO.class);
        } else {
            //2 没有重新查询
            //3 根据当前登录用户获取当前角色
            if (Collections3.isEmpty(currentUser.getRoleIds())) {
                return Collections3.emptyList();
            }
            Boolean administrator = roleServiceImpl.checkIsAdministrator(currentUser.getRoleIds());
            List<PermissionBO> permissionBos = getBean().queryAllList(FrontendTypeEnum.GLOBAL.getCode(), PublishStatusEnum.ENABLE.getValue(), null);
            if (Collections3.isEmpty(permissionBos)) {
                return Collections3.emptyList();
            }
            if (administrator) {
                result = JsonUtils.jsonToList(permissionBos, CurrentPermissionVO.class);
            } else {
                //4 根据角色查询权限
                List<RolePermissionBO> rolePermissionBos = rolePermissionServiceImpl.queryRolePermissionByRoleIds(currentUser.getRoleIds());
                if (Collections3.isEmpty(rolePermissionBos)) {
                    return Collections3.emptyList();
                }
                //5 根据权限查询所有上级权限
                List<Long> recordIds = rolePermissionBos.parallelStream().map(RolePermissionBO::getPermissionId).collect(Collectors.toList());
                List<CurrentPermissionVO> temp = JsonUtils.jsonToList(permissionBos, CurrentPermissionVO.class);
                List<Long> resultIds = new ArrayList<>();
                TreeFastUtils.selectLongPidByCid(resultIds, temp, recordIds);
                resultIds.addAll(recordIds);
                //6 根据id过滤权限信息
                result = new ArrayList<>();
                temp.stream().filter(currentPermissionVO -> resultIds.contains(currentPermissionVO.getId())).forEach(result::add);
            }
            if (Collections3.isEmpty(result)) {
                return Collections3.emptyList();
            }
            //7 存入缓存
            redisUtils.hSet(RedisKeyConstant.MODULE_G + RedisKeyConstant.USER_PERMISSION + currentUser.getId(), jti, result, RedisKeyConstant.HALF_DAY);
        }
        //8 转换数据格式并返回
        return TreeFastUtils.listToTree(result, GlobalConstant.PARENT_ID);
    }

    @Override
    public List<PermissionDTO> queryByModules(List<String> modules) {
        List<PermissionDO> permissionDos = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .orderByAsc(PermissionDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
                .eq(PermissionDO::getPublishStatus, PublishStatusEnum.ENABLE.getValue())
                .in(PermissionDO::getModule, modules)
        );
        if (Collections3.isEmpty(permissionDos)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(permissionDos, PermissionDTO.class);
    }

    @Override
    public List<GlobalIndustryDTO> queryAllGlobalIndustry(String industry, String frontend){
        List<GlobalIndustryDTO> results = new ArrayList<>();
        List<String> industyList = new ArrayList<>();
        ResponseResult<List<DictDTO>> responseResult = globalClient.queryDictByType(GlobalConstant.GLOBAL_INDUSTRY_TYPE_KEY);
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            return Collections3.emptyList();
        }
        ResponseResult<List<IndustryFrontendDTO>> industryResult = globalClient.queryIndustryFrontend(industry, frontend);
        if (null != industryResult && Collections3.isNotEmpty(industryResult.getData())) {
            List<IndustryFrontendDTO> industryFrontendList = industryResult.getData();
            industyList = industryFrontendList.stream().map(s -> s.getIndustry()).collect(Collectors.toList());
        }
        LogUtils.info("queryAllGlobalIndustry industyList>>> {}", JsonUtils.toJsonStr(industyList));
        List<DictDTO> dictDTOS = responseResult.getData();
        if(Collections3.isNotEmpty(dictDTOS)){
            List<DictDTO> sortedDictDTOS = dictDTOS.stream().sorted(Comparator.comparing(DictDTO::getSort)).collect(Collectors.toList());
            for(DictDTO s: sortedDictDTOS) {
                //if (industyList.contains(s.getValue())) {
                    GlobalIndustryDTO industryDTO = new GlobalIndustryDTO();
                    industryDTO.setId(s.getId());
                    industryDTO.setCode(s.getValue());
                    industryDTO.setName(s.getLabel());
                    industryDTO.setRemark(s.getRemark());
                    industryDTO.setPublishStatus(PublishStatusEnum.ENABLE.getValue());
                    results.add(industryDTO);
                }
            //}
        }
        return results;
    }

    @CacheEvict(cacheName = RedisKeyConstant.MODULE_G, key = "industry")
    @Override
    public FrontEndTypeVO queryFrontEndValid(String industry){
        FrontEndTypeVO results = new FrontEndTypeVO();
        QueryWrapper<PermissionDO> queryWrapper = new QueryWrapper<PermissionDO>()
                .select("module")
                .eq("industry", industry)
                .groupBy("module");
        List<Map<String, Object>> moduleList = permissionMapper.selectMaps(queryWrapper).stream().distinct().collect(Collectors.toList());
        if(Collections3.isNotEmpty(moduleList)){
            moduleList.stream().forEach(s->{
                if(FrontendTypeEnum.TENANT.getCode().equalsIgnoreCase(s.get("module").toString())){
                    results.setTenant(true);
                }else if(FrontendTypeEnum.SHOP.getCode().equalsIgnoreCase(s.get("module").toString())){
                    results.setShop(true);
                }else if(FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equalsIgnoreCase(s.get("module").toString())){
                    results.setCs(true);
                }else if(FrontendTypeEnum.CP.getCode().equalsIgnoreCase(s.get("module").toString())){
                    results.setCp(true);
                }else if(FrontendTypeEnum.APP.getCode().equalsIgnoreCase(s.get("module").toString())){
                    results.setApp(true);
                }
            });
        }
        return results;
    }

    @Override
    public List<PermissionDTO> queryListByIds(List<Long> ids) {
        List<PermissionDO> permissionDos = permissionMapper.selectList(new LambdaQueryWrapper<>(PermissionDO.class)
                .orderByAsc(PermissionDO::getSort)
                .orderByDesc(BaseDO::getCreateTime)
                .eq(PermissionDO::getPublishStatus, PublishStatusEnum.ENABLE.getValue())
                .in(PermissionDO::getId, ids)
        );
        if (Collections3.isEmpty(permissionDos)) {
            return Collections3.emptyList();
        }
        return JsonUtils.jsonToList(permissionDos, PermissionDTO.class);
    }

    @Override
    public Boolean syncAdd(PermissionDO permissionDO) {
        String sql;
        if (FrontendTypeEnum.TENANT.getCode().equals(permissionDO.getModule())) {
            //租户端
            sql = SqlUtils.insertSql(JsonUtils.fromJson(permissionDO, TenantPermissionDO.class));
        } else if (FrontendTypeEnum.SHOP.getCode().equals(permissionDO.getModule())) {
            //商户端
            sql = SqlUtils.insertSql(JsonUtils.fromJson(permissionDO, ShopPermissionDO.class));
        } else if (FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equals(permissionDO.getModule())) {
            //客服台
            sql = SqlUtils.insertSql(JsonUtils.fromJson(permissionDO, CsPermissionDO.class));
        } else if (FrontendTypeEnum.CP.getCode().equals(permissionDO.getModule())) {
            //客服台
            sql = SqlUtils.insertSql(JsonUtils.fromJson(permissionDO, CpPermissionDO.class));
        } else {
            sql = "";
        }
        if (StringUtils.isBlank(sql)) {
            return true;
        }
        List<Integer> tenantIds = tenantIds();
        if(Collections3.isEmpty(tenantIds))
            tenantIds = new ArrayList<>();
        tenantIds.add(GlobalConstant.ZERO);
        TenantDataPushParam param = DataPushUtils.getSqlParam(tenantIds, Arrays.asList(sql), ApplicationEnum.UPMS_B_APP, "菜单新增");
        param.setIndustry(permissionDO.getIndustry());
        param.setModule(permissionDO.getModule());
        ResponseResult<Boolean> responseResult = tenantDataPushClient.pushScript(param);
        if (null == responseResult || !responseResult.getData()) {
            throw new BusinessException("菜单新增数据分发异常");
        }
        return true;
    }

    @Override
    public Boolean syncModify(PermissionDO permissionDO) {
        String sql;
        if (FrontendTypeEnum.TENANT.getCode().equals(permissionDO.getModule())) {
            //租户端
            sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, TenantPermissionDO.class));
        } else if (FrontendTypeEnum.SHOP.getCode().equals(permissionDO.getModule())) {
            //商户端
            sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, ShopPermissionDO.class));
        } else if (FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equals(permissionDO.getModule())) {
            //客服台
            sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, CsPermissionDO.class));
        }  else if (FrontendTypeEnum.CP.getCode().equals(permissionDO.getModule())) {
            //客服台
            sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, CpPermissionDO.class));
        }  else {
            sql = "";
        }
        List<Integer> tenantIds = tenantIds();
        if(Collections3.isEmpty(tenantIds))
            tenantIds = new ArrayList<>();
        tenantIds.add(GlobalConstant.ZERO);
        TenantDataPushParam param = DataPushUtils.getSqlParam(tenantIds, Arrays.asList(sql), ApplicationEnum.UPMS_B_APP, "菜单修改");
        param.setIndustry(permissionDO.getIndustry());
        param.setModule(permissionDO.getModule());
        ResponseResult<Boolean> responseResult = tenantDataPushClient.pushScript(param);
        if (null == responseResult || !responseResult.getData()) {
            throw new BusinessException("菜单修改数据分发异常");
        }
        return true;
    }

    @Override
    public Boolean syncCopy(String industry, String module, List<PermissionDO> permissionDOS) {
        List<String> sqls = new ArrayList<>();
        if(Collections3.isNotEmpty(permissionDOS)) {
            permissionDOS.stream().forEach(s->{
                String sql;
                if (FrontendTypeEnum.TENANT.getCode().equals(s.getModule())) {
                    //租户端
                    sql = SqlUtils.updateSql(JsonUtils.fromJson(s, TenantPermissionDO.class));
                } else if (FrontendTypeEnum.SHOP.getCode().equals(s.getModule())) {
                    //商户端
                    sql = SqlUtils.updateSql(JsonUtils.fromJson(s, ShopPermissionDO.class));
                } else if (FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equals(s.getModule())) {
                    //客服台
                    sql = SqlUtils.updateSql(JsonUtils.fromJson(s, CsPermissionDO.class));
                }  else if (FrontendTypeEnum.CP.getCode().equals(s.getModule())) {
                    //客服台
                    sql = SqlUtils.updateSql(JsonUtils.fromJson(s, CpPermissionDO.class));
                }  else {
                    sql = "";
                }
                sqls.add(sql);
            });
            List<Integer> tenantIds = tenantIds();
            if(Collections3.isEmpty(tenantIds))
                tenantIds = new ArrayList<>();
            tenantIds.add(GlobalConstant.ZERO);
            TenantDataPushParam param = DataPushUtils.getSqlParam(tenantIds, sqls, ApplicationEnum.UPMS_B_APP, "菜单复制新增");
            param.setIndustry(industry);
            param.setModule(module);
            ResponseResult<Boolean> responseResult = tenantDataPushClient.pushScript(param);
            if (null == responseResult || !responseResult.getData()) {
                throw new BusinessException("菜单复制数据分发异常");
            }
        }
        return true;
    }

    @Override
    public Boolean syncChangeStatus(String industry, String module, List<Long> ids, Integer status) {
        List<String> sqls = new ArrayList<>();
        ids.stream().forEach(id -> {
            PermissionDO permissionDO = new PermissionDO();
            permissionDO.setId(id);
            permissionDO.setIndustry(industry);
            permissionDO.setPublishStatus(status);
            permissionDO.setModifyTime(LocalDateTime.now());
            String sql;
            if (FrontendTypeEnum.TENANT.getCode().equals(module)) {
                //租户端
                sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, TenantPermissionDO.class));
            } else if (FrontendTypeEnum.SHOP.getCode().equals(module)) {
                //商户端
                sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, ShopPermissionDO.class));
            } else if (FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equals(module)) {
                //客服台
                sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, CsPermissionDO.class));
            } else if (FrontendTypeEnum.CP.getCode().equals(module)) {
                //客服台
                sql = SqlUtils.updateSql(JsonUtils.fromJson(permissionDO, CpPermissionDO.class));
            } else {
                sql = "";
            }
            if (StringUtils.isNotBlank(sql)) {
                sqls.add(sql);
            }
        });
        List<Integer> tenantIds = tenantIds();
        if(Collections3.isEmpty(tenantIds))
            tenantIds = new ArrayList<>();
        tenantIds.add(GlobalConstant.ZERO);
        TenantDataPushParam param = DataPushUtils.getSqlParam(tenantIds, sqls, ApplicationEnum.UPMS_B_APP, "菜单修改状态");
        param.setIndustry(industry);
        param.setModule(module);
        ResponseResult<Boolean> responseResult = tenantDataPushClient.pushScript(param);
        if (null == responseResult || !responseResult.getData()) {
            throw new BusinessException("菜单修改状态数据分发异常");
        }
        return true;
    }

    @Override
    public Boolean syncDel(String industry, String module, List<Long> ids) {
        List<String> sqls = new ArrayList<>();
        ids.stream().forEach(id -> {
            PermissionDO permissionDO = new PermissionDO();
            permissionDO.setId(id);
            permissionDO.setIndustry(industry);
            String sql;
            if (FrontendTypeEnum.TENANT.getCode().equals(module)) {
                //租户端
                sql = SqlUtils.deleteSql(JsonUtils.fromJson(permissionDO, TenantPermissionDO.class));
            } else if (FrontendTypeEnum.SHOP.getCode().equals(module)) {
                //商户端
                sql = SqlUtils.deleteSql(JsonUtils.fromJson(permissionDO, ShopPermissionDO.class));
            } else if (FrontendTypeEnum.CUSTOMER_SERVICE.getCode().equals(module)) {
                //客服台
                sql = SqlUtils.deleteSql(JsonUtils.fromJson(permissionDO, CsPermissionDO.class));
            } else if (FrontendTypeEnum.CP.getCode().equals(module)) {
                //客服台
                sql = SqlUtils.deleteSql(JsonUtils.fromJson(permissionDO, CpPermissionDO.class));
            } else {
                sql = "";
            }
            if (StringUtils.isNotBlank(sql)) {
                sqls.add(sql);
            }
        });
        List<Integer> tenantIds = tenantIds();
        if(Collections3.isEmpty(tenantIds))
            tenantIds = new ArrayList<>();
        tenantIds.add(GlobalConstant.ZERO);
        TenantDataPushParam param = DataPushUtils.getSqlParam(tenantIds, sqls, ApplicationEnum.UPMS_B_APP, "菜单删除");
        param.setIndustry(industry);
        param.setModule(module);
        ResponseResult<Boolean> responseResult = tenantDataPushClient.pushScript(param);
        if (null == responseResult || !responseResult.getData()) {
            throw new BusinessException("菜单删除数据分发异常");
        }
        return true;
    }

    private List<Integer> tenantIds() {
        ResponseResult<List<Integer>> responseResult = globalClient.queryTenantIds();
        if (null == responseResult || Collections3.isEmpty(responseResult.getData())) {
            return Collections3.emptyList();
        }
        return responseResult.getData();
    }

    private IGmcPermissionService getBean() {
        return SpringBeanUtil.getBean(IGmcPermissionService.class);
    }


}
